package com.weharvest.edu.token;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import net.minidev.json.JSONObject;


import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import sun.applet.Main;

/**
 * jwt
 */
public class Jwt {

	/**
	 * 秘钥
	 */
	private static final byte[] SECRET = "3d990d2276917dfac04467df11fff26d".getBytes();

	/**
	 * 初始化head部分的数据为 { "alg":"HS256", "type":"JWT" }
	 */
	private static final JWSHeader header = new JWSHeader(JWSAlgorithm.HS256,
			JOSEObjectType.JWT, null, null, null, null, null, null, null, null, null, null, null);

	/**
	 * 生成token，该方法只在用户登录成功后调用
	 * map集合,可以存储用户id,token生成时间，token过期时间等自定义字段
	 * @param
	 * @return token字符串,若失败则返回null
	 */
	public static String createToken(Map<String, Object> payload) {
		String tokenString = null;
		// 创建一个 JWS object
		JWSObject jwsObject = new JWSObject(header, new Payload(new JSONObject(payload)));
		try {
			// 将jwsObject 进行HMAC签名
			jwsObject.sign(new MACSigner(SECRET));
			tokenString = jwsObject.serialize();
		} catch (JOSEException e) {
			System.err.println("签名失败:" + e.getMessage());
			e.printStackTrace();
		}
		return tokenString;
	}

	/**
	 * 校验token是否合法，返回Map集合,集合中主要包含 state状态码 data鉴权成功后从token中提取的数据
	 * 该方法在过滤器中调用，每次请求API时都校验
	 * 
	 * @param token
	 * @return Map<String, Object>
	 */
	public static Map<String, Object > validToken  (String token) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			JWSObject jwsObject = JWSObject.parse(token);
			Payload payload = jwsObject.getPayload();
			JWSVerifier verifier = new MACVerifier(SECRET);
			if ( jwsObject.verify(verifier) ) {
				JSONObject jsonOBj = payload.toJSONObject();
				// token校验成功（此时没有校验是否过期）
				resultMap.put("state", TokenState.VALID.toString());
				// 若payload包含ext字段，则校验是否过期
				if ( jsonOBj.containsKey("ext") ) {
					long getTime = Long.valueOf(jsonOBj.get("iat").toString());
					long extTime = Long.valueOf(jsonOBj.get("ext").toString());
					long curTime = new Date().getTime();
					// 过期了
					if (curTime > extTime + getTime) {
						resultMap.clear();
						resultMap.put("state", TokenState.EXPIRED.toString());
						return resultMap;
					}
				}
				resultMap.put("data", jsonOBj);

			} else {
				// 校验失败
				resultMap.put("state", TokenState.INVALID.toString());
			}

		} catch (Exception e) {
			// e.printStackTrace();
			// token格式不合法导致的异常
			e.printStackTrace();
			resultMap.clear();
			resultMap.put("state", TokenState.INVALID.toString());
		}
		return resultMap;
	}

	/**
     * 由字符串生成加密key
     * @return
     */
    public SecretKey generalKey(){
    	String  miyao="";
//        String stringKey = jianshu+Constant.JWT_SECRET;
        byte[] encodedKey = Base64.decodeBase64("123");
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

	public static void main(String[] args) {
    	Map<String,Object>payload=new HashMap<>();
    	payload.put("uid","123");
    	Date date=new Date();
    	long  ext =60*60*24*1000;
    	payload.put("ext",ext);
    	payload.put("iat",date.getTime());
    	String token=Jwt.createToken(payload);
    	System.out.println("token生成："+token);
		Map<String,Object>map=Jwt.validToken(token);
		System.out.println(map.toString());

	}
}
